#include "BSP/BATTERY/battery.h"

/* 去极值滤波静态缓存 */
static uint16_t adc_buf[BAT_FILTER_LEN];
static uint8_t buf_cnt = 0; // 当前已存点数
static uint8_t idx = 0;     // 循环写指针 */

/**
 * @brief  获取经过“去极值平均”后的 ADC 原始值
 * @retval 滤波后的 12-bit ADC 值
 */
static uint16_t battery_get_adc_filtered(void)
{
    /* 1. 把最新采样写进循环缓存 */
    adc_buf[idx++] = GET_ADC();
    if (idx >= BAT_FILTER_LEN)
        idx = 0;
    if (buf_cnt < BAT_FILTER_LEN)
        buf_cnt++;

    /* 2. 点数不足时直接返回最新值，避免开机阶段延迟 */
    if (buf_cnt < BAT_FILTER_LEN)
        return adc_buf[(idx + BAT_FILTER_LEN - 1) % BAT_FILTER_LEN];

    /* 3. 拷贝一份，避免破坏原始缓存 */
    uint16_t tmp[BAT_FILTER_LEN];
    for (uint8_t i = 0; i < BAT_FILTER_LEN; i++)
        tmp[i] = adc_buf[i];

    /* 4. 简易排序（冒泡足够） */
    for (uint8_t i = 0; i < BAT_FILTER_LEN - 1; i++)
    {
        for (uint8_t j = 0; j < BAT_FILTER_LEN - 1 - i; j++)
        {
            if (tmp[j] > tmp[j + 1])
            {
                uint16_t t = tmp[j];
                tmp[j] = tmp[j + 1];
                tmp[j + 1] = t;
            }
        }
    }

    /* 5. 去掉最大/最小各 x 个后求平均 */
    uint32_t sum = 0;
    for (uint8_t i = BAT_FILTER_DROP; i < BAT_FILTER_LEN - BAT_FILTER_DROP; i++)
        sum += tmp[i];
    return (uint16_t)(sum / (BAT_FILTER_LEN - 2 * BAT_FILTER_DROP));
}

/**
 * @brief       获取电池电压（单位：V）
 * @retval      电池电压
 */
float battery_get_voltage(void)
{
    uint16_t adc_value = battery_get_adc_filtered();
    float voltage = (adc_value / BATTERY_ADC_MAX) * BATTERY_ADC_VREF * BATTERY_VOLTAGE_DIVIDER;
    return voltage + BATTERY_OFFSET_V;
}

/**
 * @brief       获取电池剩余电量百分比（0~100）
 * @retval      电量百分比
 */
uint8_t battery_get_percentage(void)
{
    float voltage = battery_get_voltage();

    if (voltage <= BATTERY_VOLTAGE_MIN)
        return 0;
    if (voltage >= BATTERY_VOLTAGE_MAX)
        return 100;

    uint8_t percentage = (uint8_t)((voltage - BATTERY_VOLTAGE_MIN) * 100.0f / (BATTERY_VOLTAGE_MAX - BATTERY_VOLTAGE_MIN));
    return percentage;
}

/**
 * @brief       检查电池是否正在充电
 * @retval      1：正在充电；0：未充电
 */
uint8_t battery_check_charge(void)
{
    if (battery_get_voltage() > BATTERY_CHARGE_VOLTAGE)
        return 1;
    else
        return 0;
}
